package com.cmii.sjw.department.control.jsc.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cmii.sjw.department.control.common.AccessTokenFetcher;
import com.cmii.sjw.department.control.jsc.mapper.IndustryEducationMapper;
import com.cmii.sjw.department.control.jsc.mapper.PracticeBasesMapper;
import com.cmii.sjw.department.control.jsc.mapper.SchoolMapMapper;
import com.cmii.sjw.department.control.jsc.mapper.SocialPracticeBasesMapper;
import com.cmii.sjw.department.control.jsc.model.IndustryEducation;
import com.cmii.sjw.department.control.jsc.model.PracticeBaseInfo;
import com.cmii.sjw.department.control.jsc.model.SchoolInfo;
import com.cmii.sjw.department.control.jsc.model.SchoolInfo;
import com.cmii.sjw.department.control.jsc.model.SocialPracticeBases;
import com.cmii.sjw.department.control.jsc.model.params.SchoolInfoParams;
import com.cmii.sjw.department.control.jsc.model.vo.SocialPracticeBasesVo;
import com.cmii.sjw.department.control.jsc.service.SocialPracticeBasesService;
import com.cmii.sjw.department.control.jsc.util.MapUtils;
import com.cmii.sjw.department.control.jsc.util.Result;
import com.cmii.sjw.department.control.jsc.vo.PracticeBaseInfoVO;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author jfh
 * @Date 2025-02-11 周二 9:18
 * @Version 1.0
 */
@Slf4j
@Service
public class SocialPracticeBasesServiceImpl implements SocialPracticeBasesService {

    @Autowired
    private SocialPracticeBasesMapper socialPracticeBasesMapper;

    @Autowired
    private PracticeBasesMapper practiceBasesMapper;

    @Autowired
    private RestTemplate restTemplate;

    private final ObjectMapper objectMapper = new ObjectMapper();

    // 接口URL列表
    private final String apiUrls = "http://23.210.23.13:9000/edu-data-management/api/v1/broker/api/36";

    @Autowired
    private SchoolMapMapper schoolInfoMapper;

    /**
     * 确认地址信息
     *
     * @return
     */
    @Override
    public Result confirmeAaddressInfo() {
        // 从配置文件或环境变量中读取 API 密钥
        String apiKey = "716c08a5bf8674ae42da7d05eb2fbb96";

        QueryWrapper<PracticeBaseInfo> queryWrapper = new QueryWrapper<>();
//        queryWrapper.eq("is_active", 1);
        List<PracticeBaseInfo> socialPracticeBasesList = practiceBasesMapper.selectList(queryWrapper);

        if (socialPracticeBasesList.isEmpty()) {
            return Result.error("未查询到有效数据");
        }

        for (PracticeBaseInfo socialPracticeBases : socialPracticeBasesList) {
            if (StringUtils.isEmpty(socialPracticeBases.getAddress())) {
                continue;
            }
            try {
                // 检查是否已经有经纬度信息，避免重复调用API
                if (socialPracticeBases.getLongitude() == null || socialPracticeBases.getLatitude() == null) {
                    Map<String, String> lonAndLat = MapUtils.getLonAndLat(socialPracticeBases.getAddress(), apiKey);
                    if (lonAndLat == null) {
                        continue;
                    }
                    String lng = lonAndLat.get("lng");
                    String lat = lonAndLat.get("lat");
                    if (lng != null && lat != null) {
                        socialPracticeBases.setLongitude(lng);
                        socialPracticeBases.setLatitude(lat);
                    }
                    // 添加延时，防止QPS超出限制
                    Thread.sleep(1000); // 延时100毫秒
                }
            } catch (Exception e) {
                // 记录日志并继续处理下一个元素
                log.error("获取地址的经度和纬度时出错: " + socialPracticeBases.getAddress(), e);
                continue;
            }
        }

        // 分批更新数据
        int batchSize = 100;
        for (int i = 0; i < socialPracticeBasesList.size(); i += batchSize) {
            List<PracticeBaseInfo> batch = socialPracticeBasesList.subList(i, Math.min(i + batchSize, socialPracticeBasesList.size()));
            practiceBasesMapper.updateBatch(batch);
        }

        return Result.success();
    }

    @Override
    public IPage<String> getAllSocialNames(Integer current, Integer size) {
        Page<PracticeBaseInfo> page = new Page<>(current, size);
        IPage<PracticeBaseInfo> basePage = practiceBasesMapper.selectPage(page, new QueryWrapper<>());
        return basePage.convert(record -> record.getName());
    }

    /**
     * 根据 district_name 获取对应的基地名称
     */
    public IPage<String> getSocialNamesByDistrict(String districtName, Integer current, Integer size) {
        Page<PracticeBaseInfo> page = new Page<>(current, size);
        QueryWrapper<PracticeBaseInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("district", districtName);
        IPage<PracticeBaseInfo> basePage = practiceBasesMapper.selectPage(page, queryWrapper);
        return basePage.convert(record -> record.getName());
    }

    /**
     * 根据名称模糊查询基地名称
     */
    public IPage<String> getSocialNamesByName(String name, Integer current, Integer size) {
        Page<PracticeBaseInfo> page = new Page<>(current, size);
        QueryWrapper<PracticeBaseInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("name", name);
        IPage<PracticeBaseInfo> basePage = practiceBasesMapper.selectPage(page, queryWrapper);
        return basePage.convert(record -> record.getName());
    }

    /**
     * 中小学实践基地首页
     *
     * @return 首页展示
     */
    @Override
    public List<PracticeBaseInfoVO> index() {
        return socialPracticeBasesMapper.countIndex();
    }

    @Override
    public Map<String, Object> countByDistrict() {
        QueryWrapper<PracticeBaseInfo> queryWrapper = Wrappers.query();
        List<PracticeBaseInfo> bases = practiceBasesMapper.selectList(queryWrapper);

        List<PracticeBaseInfo> filteredBases = bases.stream()
                .filter(base -> base.getDistrict() != null)
                .collect(Collectors.toList());

        // 统计每个区县的社会实践基地数量
        Map<String, Long> districtCounts = filteredBases.stream()
                .collect(Collectors.groupingBy(PracticeBaseInfo::getDistrict, Collectors.counting()));

        // 按社会实践基地数量降序排序
        Map<String, Long> sortedDistrictCounts = districtCounts.entrySet().stream()
                .sorted(Map.Entry.<String, Long>comparingByValue(Comparator.reverseOrder()))
                .collect(Collectors.toMap(
                        Map.Entry::getKey,
                        Map.Entry::getValue,
                        (e1, e2) -> e1,
                        LinkedHashMap::new));

        // 计算总数
        long totalCount = bases.size();

        List<Map<String, String>> resultData = new ArrayList<>();

        for (Map.Entry<String, Long> entry : sortedDistrictCounts.entrySet()) {
            String district = entry.getKey();
            long count = entry.getValue();

            Map<String, String> entryMap = new HashMap<>();
            entryMap.put("areaname", district);
            entryMap.put("count", String.valueOf(count));
            resultData.add(entryMap);
        }

        // 构建最终结果
        Map<String, Object> result = new LinkedHashMap<>();
        result.put("totalCount", totalCount);
        result.put("data", resultData);

        return result;
    }

    /**
     * 中小学实践基地
     *
     * @return 数据入库
     */
    @Override
    public void saveData() {
        try {
            List<PracticeBaseInfo> practiceBaseInfoList = getValueFromApiWithTime(apiUrls);
            if (practiceBaseInfoList != null && !practiceBaseInfoList.isEmpty()) {
                // 清空表中的现有数据
                try {
                    practiceBasesMapper.delete(null);
                    log.info("成功清空表中的现有数据");
                } catch (Exception e) {
                    log.error("清空表失败: {}", e.getMessage(), e);
                    return;
                }

                // 将结果保存到数据库
                for (PracticeBaseInfo practiceBaseInfo : practiceBaseInfoList) {
                    try {
                        practiceBasesMapper.insert(practiceBaseInfo);
                        log.info("成功存入数据库: {}", practiceBaseInfo.getName());
                    } catch (Exception e) {
                        log.error("存入失败: {}", e.getMessage(), e);
                    }
                }
            }
        } catch (Exception e) {
            log.error("API调用失败: {}", e.getMessage(), e);
        }
    }

    @Override
    public Result socialPracticeBasesMapDetailed(SchoolInfoParams params) {
        Map<String, Object> result = new HashMap<>();
        //查询重庆市默认查询全部
        if ("重庆市".equals(params.getAreaName())) params.setAreaName(null);

        List<SocialPracticeBasesVo> schoolList = schoolInfoMapper.socialPracticeBasesMapDetailed(params.getAreaName(), params.getName());
        result.put("schoolList", schoolList);

        return Result.success(result);
    }

    private List<PracticeBaseInfo> getValueFromApiWithTime(String baseUrl) {
        try {
            String accessToken = new AccessTokenFetcher().fetchAccessToken();
            log.info("使用的访问令牌: {}", accessToken);

            HttpHeaders headers = new HttpHeaders();
            headers.set("X-Auth-Token", accessToken);
            headers.setContentType(MediaType.APPLICATION_JSON);

            int page = 1;
            int pageSize = 10000;
            List<PracticeBaseInfo> allPracticeBases = new ArrayList<>();

            String url = baseUrl + "?page=" + page + "&pageSize=" + pageSize;
            HttpEntity<?> entity = new HttpEntity<>(headers);

            ResponseEntity<String> response = restTemplate.exchange(
                    url,
                    HttpMethod.GET,
                    entity,
                    String.class
            );

            if (response.getStatusCode().is2xxSuccessful()) {
                String responseBody = response.getBody();
                JsonNode jsonNode = objectMapper.readTree(responseBody);

                JsonNode resultsNode = jsonNode.path("results");
                if (resultsNode.isArray()) {
                    for (JsonNode resultNode : resultsNode) {
                        PracticeBaseInfo practiceBaseInfo = new PracticeBaseInfo()
                                .setId(resultNode.path("id").asLong())
                                .setParentId(resultNode.path("parent_id").asInt())
                                .setName(resultNode.path("base_name").asText())
                                .setCode(resultNode.path("base_code").asText())
                                .setCover(resultNode.path("base_cover").asText())
                                .setLevel(resultNode.path("base_level").asInt())
                                .setType(resultNode.path("base_type").asText())
                                .setScale(resultNode.path("scale").asInt())
                                .setProvince(resultNode.path("province").asText())
                                .setCity(resultNode.path("city").asText())
                                .setArea(resultNode.path("area").asText())
                                .setPoint(resultNode.path("point").asText())
                                .setLongitude(resultNode.path("longitude").asText())
                                .setLatitude(resultNode.path("latitude").asText())
                                .setDistrict(resultNode.path("district").asText())
                                .setAddress(resultNode.path("address").asText())
                                .setLegalPerson(resultNode.path("legal_person").asText())
                                .setContacts(resultNode.path("contacts").asText())
                                .setPhone(resultNode.path("phone").asText())
                                .setEmail(resultNode.path("base_email").asText())
                                .setBriefIntroduction(resultNode.path("brief_introduction").asText())
                                .setMaxReceptionNum(resultNode.path("max_reception_num").asInt())
                                .setCoverArea(resultNode.path("cover_area").asText())
                                .setFloorArea(resultNode.path("floor_area").asText())
                                .setVenueIndoorNum(resultNode.path("venue_indoor_num").asText())
                                .setVenueOutdoorNum(resultNode.path("venue_outdoor_num").asText())
                                .setDormNum(resultNode.path("dorm_num").asInt())
                                .setTeacherNum(resultNode.path("teacher_num").asInt())
                                .setMaxMealsNum(resultNode.path("max_meals_num").asInt())
                                .setOpeningTime(resultNode.path("opening_time").asText())
                                .setImages(resultNode.path("images").asText())
                                .setVideos(resultNode.path("videos").asText())
                                .setIsEnabled(resultNode.path("is_enabled").asBoolean())
                                .setTotalViews(resultNode.path("total_views").asInt())
                                .setTotalReceptionists(resultNode.path("total_receptionists").asInt())
                                .setTotalEvaluations(resultNode.path("total_evaluations").asInt())
                                .setTotalCourses(resultNode.path("total_courses").asInt())
                                .setTotalActivities(resultNode.path("total_activities").asInt())
                                .setIsTopped(resultNode.path("is_topped").asBoolean())
                                .setDisabledAt(resultNode.path("disabled_at").asText())
                                .setDisabledBy(resultNode.path("disabled_by").asText())
                                .setDisabledContent(resultNode.path("disabled_content").asText())
                                .setFirstAuditAt(resultNode.path("first_audit_at").asText())
                                .setAuditStatus(resultNode.path("audit_status").asBoolean())
                                .setAuditAt(resultNode.path("audit_at").asText())
                                .setAuditBy(resultNode.path("audit_by").asText())
                                .setAuditContent(resultNode.path("audit_content").asText())
                                .setDemoteStatus(resultNode.path("demote_status").asBoolean())
                                .setDemoteAt(resultNode.path("demote_at").asText())
                                .setDemoteBy(resultNode.path("demote_by").asText())
                                .setDemoteContent(resultNode.path("demote_content").asText())
                                .setDemoteConfirmAt(resultNode.path("demote_confirm_at").asText())
                                .setDemoteConfirmBy(resultNode.path("demote_confirm_by").asText())
                                .setDemoteConfirmContent(resultNode.path("demote_confirm_content").asText())
                                .setCommentStatus(resultNode.path("comment_status").asBoolean())
                                .setCreateAt(resultNode.path("create_at").asText())
                                .setCreateBy(resultNode.path("create_by").asText())
                                .setCreatorId(resultNode.path("creator_id").asInt())
                                .setCreatorIdentity(resultNode.path("creator_identity").asText())
                                .setUpdateAt(resultNode.path("update_at").asText())
                                .setUpdateBy(resultNode.path("update_by").asText())
                                .setUpdatorId(resultNode.path("updater_id").asInt())
                                .setUpdatorIdentity(resultNode.path("updater_identity").asText());

                        allPracticeBases.add(practiceBaseInfo);
                    }
                    int totalCount = jsonNode.path("totalCount").asInt();
                    if (allPracticeBases.size() >= totalCount) {

                    }

                    page++;
                } else {
                    log.error("响应中未找到有效的结果: {}", responseBody);
                    throw new RuntimeException("响应中未找到有效的结果");
                }
            } else {
                log.error("HTTP 请求返回: {} {}", url, response.getStatusCodeValue());
                throw new RuntimeException("API 请求返回状态码异常");
            }

            return allPracticeBases;
        } catch (Exception e) {
            log.error("API调用失败 {}: {}", baseUrl, e.getMessage(), e);
            throw new RuntimeException("API 调用失败", e);
        }
    }
}
